package cn.com.zero.base.util;

import cn.hutool.crypto.SecureUtil;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;

/**
 * @author liuxh
 * @version 1.0.0
 * @Description 敏感信息工具
 * @createTime 2023/3/31 11:08
 */
@Configuration
@ConfigurationProperties(prefix = "zero.secret-key")
public class SensitiveInfoUtil {

    /**
     * 姓名保留长度
     */
    public static final int NAME_LENGTH = 2;
    // 手机号密钥
    private static String mobileSecretKey;
    // 证件号密钥
    private static String cardNoSecretKey;


    /**
     * 手机号加密
     *
     * @param mobile 手机号
     * @return 手机号加密串
     */
    public static String encryptMobile(String mobile) {
        return SecureUtil.aes(mobileSecretKey.getBytes()).encryptHex(mobile);
    }

    /**
     * 手机号解密
     *
     * @param encryptMobile 手机号加密串
     * @return 手机号加密串
     */
    public static String decryptMobile(String encryptMobile) {
        return SecureUtil.aes(mobileSecretKey.getBytes()).decryptStr(encryptMobile);
    }

    /**
     * 手机号转换<br/>
     * 转换后前边保留3位，后边保留4位，其余替换成 * 号
     *
     * @param mobile 手机号
     * @return String 转换后手机号
     */
    public static String encodeMobile(String mobile) {
        return encode(mobile, 3, 4);
    }


    /**
     * 密码加密
     *
     * @param password 密码
     * @return 密码加密串
     */
    public static String encryptPwd(String password) {

        return new BCryptPasswordEncoder().encode(password);
    }

    /**
     * 密码是否匹配
     *
     * @param rawPassword     密码明文
     * @param encodedPassword 密码密文
     * @return true：密码匹配 false：密码不匹配
     */
    public static boolean matchesPwd(String rawPassword, String encodedPassword) {
        return new BCryptPasswordEncoder().matches(rawPassword, encodedPassword);
    }


    /**
     * 替换特殊字符
     *
     * @param str      字符明文
     * @param firstLen 首端保留位数
     * @param lastLen  末尾保留位数
     * @return 替换特殊字符后的信息
     */
    public static String encode(String str, int firstLen, int lastLen) {
        if (!StringUtils.hasLength(str)) {
            return str;
        }
        /*
         * (?<=.{3}).(?=.{2}) 表达式说明
         * . 表示任何字符
         * (?<=.{3}) 表示字符串前边的三个字符保留
         * (?=.{2}) 表示字符串后边的两个字符保留
         * 中间的 . 表示其余字符替换
         */
        String regEx = "(?<=.{" + firstLen + "}).(?=.{" + lastLen + "})";

        return str.replaceAll(regEx, "*");
    }


    /**
     * 姓名转换<br/>
     * 转换后如果姓名为2个字，则前边保留1位
     *
     * @param name 姓名
     * @return 转换后姓名
     */
    public static String encodeName(String name) {
        if (!StringUtils.hasLength(name)) {
            return name;
        }

        if (name.length() <= NAME_LENGTH) {
            return encode(name, 1, 0);
        }
        return encode(name, 1, NAME_LENGTH-1);
    }


    /**
     * 证件号加密
     *
     * @param cardNo 手机号
     * @return 手机号加密串
     */
    public static String encryptCardNo(String cardNo) {
        return SecureUtil.aes(cardNoSecretKey.getBytes()).encryptHex(cardNo);
    }

    /**
     * 证件号解密
     *
     * @param encryptCardNo 证件号加密串
     * @return 手机号加密串
     */
    public static String decryptCardNo(String encryptCardNo) {
        return SecureUtil.aes(cardNoSecretKey.getBytes()).decryptStr(encryptCardNo);
    }

    /**
     * 证件号码转换<br/>
     * 转换后前边保留3位，后边保留4位，其余替换成 * 号
     *
     * @param cardNo 证件号码
     * @return 转换后证件号
     */
    public static String encodeCardNo(String cardNo) {
        return encode(cardNo, 3, 4);
    }


    @ConfigurationProperties("mobile")
    public void setMobile(String mobile) {
        SensitiveInfoUtil.mobileSecretKey = mobile;
    }

    @ConfigurationProperties("cardNo")
    public void setCardNo(String cardNo) {
        SensitiveInfoUtil.cardNoSecretKey = cardNo;
    }
}
